/*
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import * as chokidar from 'chokidar';
import { Logger } from '../../core';
import { TaskConstants } from '../constants/TaskConstants';
import { ITargetContext } from '../interfaces/ITargetContext';
import { BaseTask } from './BaseTask';

export class WatchTask extends BaseTask {
  readonly taskName: string = TaskConstants.WATCH_TASK;
  readonly dependencies: string[] = []; // CLI任务无依赖
  readonly postDependencies: string[] = []; // CLI任务无依赖

  private watcher?: chokidar.FSWatcher;

  async run(context: ITargetContext): Promise<void> {
    Logger.info('Start the file listening task');

    const watchPaths = this.getScanFiles(context);
    if (watchPaths.length === 0) {
      Logger.info('There are no files to listen to');
      return;
    }

    Logger.info(`Start listening for file changes: ${watchPaths.join(', ')}`);

    // 创建文件监听器
    this.watcher = chokidar.watch(watchPaths, {
      persistent: true,
      ignoreInitial: false // 初始时也触发一次
    });

    // 设置事件监听器
    this.setupWatchEvents(context);

    Logger.info('File monitoring has been started. Press Ctrl+C to stop the monitoring');

    return new Promise(_resolve => {
      // 进程会一直运行，直到用户手动停止
      // resolve永远不会被调用，除非出现错误或用户停止
    });
  }

  private setupWatchEvents(context: ITargetContext): void {
    if (!this.watcher) return

    let debounceTimer: NodeJS.Timeout | null = null

    // 防抖处理，避免频繁触发
    const debouncedGenerate = (filePath: string) => {
      if (debounceTimer) {
        clearTimeout(debounceTimer)
      }
      debounceTimer = setTimeout(() => {
        this.generateCode(filePath, context)
      }, 500) // 500ms 防抖
    }

    this.watcher
      .on('add', (filePath: string) => {
        Logger.info(`New file detected: ${filePath}`)
        debouncedGenerate(filePath)
      })
      .on('change', (filePath: string) => {
        Logger.info(`File change detected: ${filePath}`)
        debouncedGenerate(filePath)
      })
      .on('unlink', (filePath: string) => {
        Logger.info(`File deletion detected: ${filePath}`)
        debouncedGenerate(filePath)
      })
      .on('error', (error: unknown) => {
        Logger.error(`File monitoring error: ${error}`)
      })
      .on('ready', () => {
        Logger.info('The initial file scan is complete. Start listening for file changes...')
      })
  }

  private generateCode(scanFile: string, context: ITargetContext): void {
    // 统一处理：逐文件分析 → 直接生成
    const processingResult = this.engine.processFileUnified(scanFile, context)

    Logger.info(`The code generation is complete, and the output path is ${processingResult?.outputPath}`)
  }
}
